import java.nio.ByteBuffer;

// RR: Receiver Report RTCP Packet

//         0                   1                   2                   3
//         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// header |V=2|P|    RC   |   PT=RR=201   |             length            |
//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//        |                     SSRC of packet sender                     |
//        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
// report |                           fraction lost                       |
// block  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//   1    |              cumulative number of packets lost                |
//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//        |           extended highest sequence number received           |
//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//        |                      interarrival jitter                      |
//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//        |                         last SR (LSR)                         |
//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//        |                   delay since last SR (DLSR)                  |
//        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

class RTCPpacket {

    final static int HEADER_SIZE = 8;
    final static int BODY_SIZE = 24;

    public int Version;            // 版本号 2
    public int Padding;            // 数据包的填充 0
    public int RC;                // 1
    public int PayloadType;        //  Receiver Report 201
    public int length;            //  32 byte, 8 + 24
    public int Ssrc;            // 同步标识符
    public float fractionLost;    // 自上一个RR数据包发送后，发送方丢失的RTP数据包的比例
    public int cumLost;            // 自接收开始，发送方丢失的RTP数据包的总数
    public int highSeqNb;        // 收到的最高序列号
    public int jitter;            //
    public int LSR;                //
    public int DLSR;            //

    public byte[] header;    //首部
    public byte[] body;        //内容


    /**
     *
     * @param fractionLost 自上一个RR数据包发送后，发送方丢失的RTP数据包的比例
     * @param cumLost 自接收开始，发送方丢失的RTP数据包的总数
     * @param highSeqNb 收到的最高序列号
     */
    public RTCPpacket(float fractionLost, int cumLost, int highSeqNb) {
        Version = 2;
        Padding = 0;
        RC = 1;
        PayloadType = 201;
        length = 32;

        this.fractionLost = fractionLost;
        this.cumLost = cumLost;
        this.highSeqNb = highSeqNb;


        header = new byte[HEADER_SIZE];
        body = new byte[BODY_SIZE];

        header[0] = (byte) (Version << 6 | Padding << 5 | RC);
        header[1] = (byte) (PayloadType & 0xFF);
        header[2] = (byte) (length >> 8);
        header[3] = (byte) (length & 0xFF);
        header[4] = (byte) (Ssrc >> 24);
        header[5] = (byte) (Ssrc >> 16);
        header[6] = (byte) (Ssrc >> 8);
        header[7] = (byte) (Ssrc & 0xFF);

        ByteBuffer bb = ByteBuffer.wrap(body);
        bb.putFloat(fractionLost);
        bb.putInt(cumLost);
        bb.putInt(highSeqNb);
    }

    // 构造rtcp包，

    /**
     *
     * @param packet
     * @param packet_size
     */
    public RTCPpacket(byte[] packet, int packet_size) {

        header = new byte[HEADER_SIZE];
        body = new byte[BODY_SIZE];

        System.arraycopy(packet, 0, header, 0, HEADER_SIZE);
        System.arraycopy(packet, HEADER_SIZE, body, 0, BODY_SIZE);

        // 首部
        Version = (header[0] & 0xFF) >> 6;
        PayloadType = header[1] & 0xFF;
        length = (header[3] & 0xFF) + ((header[2] & 0xFF) << 8);
        Ssrc = (header[7] & 0xFF) + ((header[6] & 0xFF) << 8) + ((header[5] & 0xFF) << 16) + ((header[4] & 0xFF) << 24);

        // 数据
        ByteBuffer bb = ByteBuffer.wrap(body); //
        fractionLost = bb.getFloat();
        cumLost = bb.getInt();
        highSeqNb = bb.getInt();
    }


    public int getPacket(byte[] packet) {
        System.arraycopy(header, 0, packet, 0, HEADER_SIZE);
        System.arraycopy(body, 0, packet, HEADER_SIZE, BODY_SIZE);

        //数据包总长度
        return BODY_SIZE + HEADER_SIZE;
    }

    public int getLength() {
        return BODY_SIZE + HEADER_SIZE;
    }

    public String toString() {
        return "[RTCP] Version: " + Version + ", Fraction Lost: " + fractionLost
                + ", Cumulative Lost: " + cumLost + ", Highest Seq Num: " + highSeqNb;
    }
}